package com.lightboat.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.lightboat.common.algorithm.GuavaLotteryService;
import com.lightboat.common.algorithm.WeightedLotteryWheel;
import com.lightboat.common.utils.DateUtils;
import com.lightboat.system.domain.CrmLogisticsAddress;
import com.lightboat.system.mapper.CrmLogisticsAddressMapper;
import com.lightboat.system.service.ICrmLogisticsAddressService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 物流地址配置Service业务层处理
 *
 * @author lightboat
 * @date 2025-08-21
 */
@Service
@RequiredArgsConstructor
public class CrmLogisticsAddressServiceImpl extends ServiceImpl<CrmLogisticsAddressMapper, CrmLogisticsAddress> implements ICrmLogisticsAddressService {

    private final CrmLogisticsAddressMapper crmLogisticsAddressMapper;

    private GuavaLotteryService<CrmLogisticsAddress> guavaLotteryService;

    /**
     * 查询物流地址配置
     *
     * @param id 物流地址配置主键
     * @return 物流地址配置
     */
    @Override
    public CrmLogisticsAddress selectCrmLogisticsAddressById(Long id) {
        return crmLogisticsAddressMapper.selectById(id);
    }

    /**
     * 查询物流地址配置列表
     *
     * @param crmLogisticsAddress 物流地址配置
     * @return 物流地址配置
     */
    @Override
    public List<CrmLogisticsAddress> selectCrmLogisticsAddressList(CrmLogisticsAddress crmLogisticsAddress) {
        return crmLogisticsAddressMapper.selectCrmLogisticsAddressList(crmLogisticsAddress);
    }

    /**
     * 新增物流地址配置
     *
     * @param crmLogisticsAddress 物流地址配置
     * @return 结果
     */
    @Override
    public int insertCrmLogisticsAddress(CrmLogisticsAddress crmLogisticsAddress) {
        crmLogisticsAddress.setCreateTime(DateUtils.getNowDate());
        return crmLogisticsAddressMapper.insert(crmLogisticsAddress);
    }

    /**
     * 修改物流地址配置
     *
     * @param crmLogisticsAddress 物流地址配置
     * @return 结果
     */
    @Override
    public int updateCrmLogisticsAddress(CrmLogisticsAddress crmLogisticsAddress) {
        crmLogisticsAddress.setUpdateTime(DateUtils.getNowDate());
        return crmLogisticsAddressMapper.updateById(crmLogisticsAddress);
    }

    /**
     * 批量删除物流地址配置
     *
     * @param ids 需要删除的物流地址配置主键
     * @return 结果
     */
    @Override
    public int deleteCrmLogisticsAddressByIds(Long[] ids) {
        return crmLogisticsAddressMapper.deleteCrmLogisticsAddressByIds(ids);
    }

    /**
     * 删除物流地址配置信息
     *
     * @param id 物流地址配置主键
     * @return 结果
     */
    @Override
    public int deleteCrmLogisticsAddressById(Long id) {
        return crmLogisticsAddressMapper.deleteCrmLogisticsAddressById(id);
    }

    @Override
    public List<CrmLogisticsAddress> getLogisticsAddress(String logisticsNo){
        LambdaQueryWrapper<CrmLogisticsAddress> wrapper = Wrappers.<CrmLogisticsAddress>lambdaQuery().eq(StrUtil.isNotBlank(logisticsNo) && !"all".equals(logisticsNo), CrmLogisticsAddress::getLogisticsNo, logisticsNo).eq(CrmLogisticsAddress::getStatus, true).eq(CrmLogisticsAddress::getType, 2);
        return crmLogisticsAddressMapper.selectList(wrapper);
    }

    @Override
    @PostConstruct
    public void initByWeight() {
        guavaLotteryService = new GuavaLotteryService<CrmLogisticsAddress>(
    CacheBuilder.newBuilder()
            .maximumSize(1000)  // 最大缓存1000个活动
            .expireAfterWrite(30, TimeUnit.MINUTES)  // 30分钟过期
            .refreshAfterWrite(10, TimeUnit.MINUTES)  // 10分钟后异步刷新
            .build(new CacheLoader<String, WeightedLotteryWheel<CrmLogisticsAddress>>() {

                /**
                 * Computes or retrieves the value corresponding to {@code key}.
                 *
                 * @param key the non-null key whose value should be loaded
                 * @return the value associated with {@code key}; <b>must not be null</b>
                 * @throws Exception            if unable to load the result
                 * @throws InterruptedException if this method is interrupted. {@code InterruptedException} is
                 *                              treated like any other {@code Exception} in all respects except that, when it is caught,
                 *                              the thread's interrupt status is set
                 */
                @Override
                public WeightedLotteryWheel<CrmLogisticsAddress> load(String key) throws Exception {
                    List<WeightedLotteryWheel.Prize<CrmLogisticsAddress>> prizes = getLogisticsAddress(key).stream().map(m -> new WeightedLotteryWheel.Prize<CrmLogisticsAddress>(m.getId().toString(), m.getLogisticsName(), m.getWeight(), m)).toList();
                    return new WeightedLotteryWheel<CrmLogisticsAddress>(prizes);
                }
            })
        );
    }

    @Override
    public CrmLogisticsAddress getLogisticsAddressByWeight(String logisticsNo) {
        return guavaLotteryService.drawPrize(logisticsNo).getData();
    }
}
